#include "project.h"

// this file has mostly low level code for reading and writing
// messages out of the network.

int
write_msg(BIO *cbio, MSG *msg)                              //function to write the message to console
{
	long ret;
	if (msg->size <= 0)
		return -1;
	while ((ret = BIO_write(cbio, &msg->size, sizeof(msg->size))) <= 0
			&& BIO_should_retry(cbio));
	if (ret < sizeof(msg->size))
		return -1;
	while ((ret = BIO_write(cbio, msg->data, msg->size)) <= 0 
			&& BIO_should_retry(cbio));
	if (ret < msg->size)
		return -1;
	return 0;
}

int
read_msg(BIO *cbio, MSG *msg)                                 //function to read the message to console
{
	int ret;
	while ((ret = BIO_read(cbio, &msg->size, sizeof(msg->size))) <= 0
			&& BIO_should_retry(cbio));
	if (ret < sizeof(msg->size) || msg->size <= 0)
		return -1;
	msg->data = malloc(msg->size);
	while ((ret = BIO_read(cbio, msg->data, msg->size)) <= 0
			&& BIO_should_retry(cbio));
	if (ret < msg->size){
		free(msg->data);
		msg->data = NULL;
		return -1;
	}
	return 0;
}


int
send_recv(MSG *msg, MSG *res)                                   //function to send and recieve the message to console
{
	BIO *cbio;
	int ret;

	cbio = BIO_new_connect((char *)"localhost:8081");
	//cbio = BIO_new_connect((char *)"aragorn.cs.purdue.edu:8081");
	if (cbio == NULL)
		return -1;
	do {
		if (BIO_do_connect(cbio) <= 0)
			break;
		if (write_msg(cbio, msg))
			break;
		if (res)
			ret = read_msg(cbio, res);
		else
			ret = 0;
		BIO_free(cbio);
		return ret;
	} while (0);

	BIO_free(cbio);
	return -1;
}

// extract CTF's public key from message created by build_ctf_public_key_MSG()
RSA *
get_ctf_public_key(MSG *msg)
{
	if (MSG_GET_CTF_PUBLIC_KEY_REPL != MSG_TYPE(msg))
		return NULL;
	int len = *(int *)((char *)msg->data + 4);
	unsigned char *Key = (unsigned char *)msg->data + 8;
	RSA *KEY = d2i_RSAPublicKey(NULL, (const unsigned char **)&Key, len);
	return KEY;
}

// package CTF's public key into a message to be sent to a voter.
MSG *
build_ctf_public_key_MSG(RSA *key)
{
	MSG *msg = (MSG *)malloc(sizeof(MSG));
	int len = i2d_RSAPublicKey(key, 0);
	msg->size = 2*sizeof(int)+len;
	msg->data = (unsigned char *)malloc(msg->size);
	MSG_TYPE(msg) = MSG_GET_CTF_PUBLIC_KEY_REPL;
	*(int *)((char *)msg->data + 4) = len;
	unsigned char *Key = (unsigned char *)msg->data + 8;
	int len2 = i2d_RSAPublicKey(key, &Key);
	if (len != len2){
		ERR_print_errors_fp(stdout);
		free(msg->data);
		free(msg);
		return NULL;
	}
	return msg;
}


void
alloc_msg(int size, MSG *msg)
{
	msg->size = size;
	msg->data = malloc(size);
}

